﻿// <copyright file="Button.cs" company="ThorIndustry">Copyright (c) ThorIndustry. All rights reserved.</copyright>

public class Button : UnityEngine.MonoBehaviour
{
    public ButtonTexture[] TextureByState;
    public UnityEngine.Color DisableColor = UnityEngine.Color.grey;

    private const float DoubleClickSensitivity = 0.5f;

    private ButtonState currentState = ButtonState.Normal;
    private UnityEngine.GUITexture localGuiTexture = null;
    private UnityEngine.GUIText localGuiText = null;

    private int clickCount = 1;
    private float lastClickTime = 0;

    private UnityEngine.Color initialColor;

    public event System.EventHandler Clicked;

    public event System.EventHandler Down;
    
    public event System.EventHandler DoubleClicked;
    
    public event System.EventHandler MouseEnter;
    
    public event System.EventHandler MouseExit;

    public event System.EventHandler Up;

    public UnityEngine.GUIText GuiText
    {
        get
        {
            if (this.localGuiText == null)
            {
                this.localGuiText = this.GetComponentInChildren<UnityEngine.GUIText>();
                if (this.localGuiText == null)
                {
                    this.localGuiText = this.gameObject.AddComponent<UnityEngine.GUIText>();
                }
            }

            return this.localGuiText;
        }
    }

    public virtual UnityEngine.GUITexture GuiTexture
    {
        get
        {
            if (this.localGuiTexture == null)
            {
                this.localGuiTexture = this.GetComponentInChildren<UnityEngine.GUITexture>();
                if (this.localGuiTexture == null)
                {
                    this.localGuiTexture = this.gameObject.AddComponent<UnityEngine.GUITexture>();
                }

                this.initialColor = this.localGuiTexture.color;
            }

            return this.localGuiTexture;
        }
    }

    public bool IsEnable
    {
        get;
        set;
    }

    public bool IsVisible
    {
        get;
        set;
    }

    public virtual void Enable(bool enable)
    {
        if (this.IsEnable == enable)
        {
            return;
        }

        // Change color to black...
        if (enable)
        {
            this.ChangeTexture(ButtonState.Normal);
        }
        else
        {
            this.ChangeTexture(ButtonState.Disable);
        }

        this.IsEnable = enable;
        this.enabled = enable;
    }

    protected virtual void ApplyStateTexture(ButtonTexture texture)
    {
        this.GuiTexture.texture = texture.Texture;
        this.GuiTexture.color = texture.Color;
    }

    protected virtual void Awake()
    {
        if (this.GuiText != null)
        {
            this.GuiText.fontSize = UnityEngine.Mathf.RoundToInt(this.GuiText.fontSize * GuiHelper.GetScreenSizeRatio());
        }
    }

#if !(UNITY_IPHONE || UNITY_ANDROID)
    protected virtual void OnMouseDown()
    {
        if (!this.IsEnable)
        {
            return;
        }

        this.ChangeTexture(ButtonState.Armed);

        if (this.Down != null)
        {
            this.Down.Invoke(this, new System.EventArgs());
        }
    }

    protected virtual void OnMouseEnter()
    {
        if (!this.IsEnable)
        {
            return;
        }

        this.ChangeTexture(ButtonState.Hover);

        if (this.MouseEnter != null)
        {
            this.MouseEnter.Invoke(this, new System.EventArgs());
        }
    }

    protected virtual void OnMouseExit()
    {
        if (!this.IsEnable)
        {
            return;
        }

        this.ChangeTexture(ButtonState.Normal);

        if (this.MouseExit != null)
        {
            this.MouseExit.Invoke(this, new System.EventArgs());
        }
    }

    protected virtual void OnMouseUp()
    {
        if (!this.IsEnable)
        {
            return;
        }

        if (UnityEngine.Time.time - lastClickTime <= Button.DoubleClickSensitivity)
        {
            ++this.clickCount;
        }
        else
        {
            this.clickCount = 1;
        }

        if (this.currentState == ButtonState.Armed)
        {
            if (clickCount == 1)
            {
                this.NotifyClicked();
            }
            else
            {
                this.NotifyDoubleClicked();
            }

            this.currentState = ButtonState.Hover;
            this.ChangeTexture(this.currentState);
        }

        lastClickTime = UnityEngine.Time.time;

        if (this.Up != null)
        {
            this.Up.Invoke(this, new System.EventArgs());
        }
    }
#endif
    
    protected virtual void Start()
    {
        this.ChangeTexture(ButtonState.Normal);
        this.Enable(true);
    }

#if (UNITY_IPHONE || UNITY_ANDROID || true)
    protected virtual void Update()
    {
        if (!this.IsEnable)
        {
            return;
        }

        int count = UnityEngine.Input.touchCount;
        for (int i = 0; i < count; i++)
        {
            UnityEngine.Touch touch = UnityEngine.Input.GetTouch(i);
            if (this.HitTest(touch.position))
            {
                if (touch.phase == UnityEngine.TouchPhase.Ended || touch.phase == UnityEngine.TouchPhase.Canceled)
                {
                    this.ChangeTexture(ButtonState.Normal);
                }
                else
                {
                    this.ChangeTexture(ButtonState.Armed);
                }

                if (touch.phase == UnityEngine.TouchPhase.Began)
                {
                    if (touch.tapCount == 1)
                    {
                        this.NotifyClicked();
                    }
                    else if (touch.tapCount == 2)
                    {
                        this.NotifyDoubleClicked();
                    }
                }

                break;
            }
        }
    }
#endif

    private void ChangeTexture(ButtonState newState)
    {
        for (int index = 0; index < this.TextureByState.Length; ++index)
        {
            if (this.TextureByState[index].State == newState)
            {
                this.currentState = newState;
                this.ApplyStateTexture(this.TextureByState[index]);
                break;
            }
        }
    }

    public bool HitTest(UnityEngine.Vector2 position)
    {
        return this.GuiTexture.HitTest(new UnityEngine.Vector3(position.x, position.y, 0));
    }

    private void NotifyClicked()
    {
        if (this.Clicked != null)
        {
            this.Clicked.Invoke(this, new System.EventArgs());
        }
    }

    private void NotifyDoubleClicked()
    {
        if (this.DoubleClicked != null)
        {
            this.DoubleClicked.Invoke(this, new System.EventArgs());
        }
    }

    public enum ButtonState
    {
        Normal,
        Hover,
        Armed,
        Disable,
    }

    [System.Serializable]
    public class ButtonTexture
    {
        public UnityEngine.Texture Texture;
        public UnityEngine.Color Color = UnityEngine.Color.white;
        public ButtonState State;
    }
}
